

#include "stdafx.h"
#include "pf_filterfont.h"

#include <iostream>
#include <fstream>

#include "pf_font.h"
#include "pf_utility.h"
#include "pf_system.h"
#include "pf_block.h"
#include "lx_String.h"


/**
 * Default constructor.
 */
PF_FilterFont::PF_FilterFont() : PF_FilterInterface() {

    PF_DEBUG->print("Setting up FONT filter...");

    addImportFormat(LX_Define::FormatFONT);
    addExportFormat(LX_Define::FormatFONT);
}



/**
 * Implementation of the method used for PF_Import to communicate
 * with this filter.
 *
 * @param g The graphic in which the entities from the file
 * will be created or the graphics from which the entities are
 * taken to be stored in a file.
 */
bool PF_FilterFont::fileImport(PF_Graphic& g, const QString& file, LX_Define::FormatType /*type*/) {
    PF_DEBUG->print("FONT Filter: importing file '%s'...", file.latin1());

    //this->graphic = &g;
    bool success = false;

    // Load font file as we normally do, but the font doesn't own the
    //  letters (we'll add them to the graphic instead. Hence 'false').
    PF_Font font(file, false);
    success = font.loadFont();

    if (success==false) {
        PF_DEBUG->print(PF_Debug::D_WARNING,
                        "Cannot open font file '%s'.", file.latin1());
		return false;
    }

    g.addVariable("Names",
                         font.getNames().join(","), 0);
    g.addVariable("LetterSpacing", font.getLetterSpacing(), 0);
    g.addVariable("WordSpacing", font.getWordSpacing(), 0);
    g.addVariable("LineSpacingFactor", font.getLineSpacingFactor(), 0);
    g.addVariable("Authors", font.getAuthors().join(","), 0);
    if (!font.getEncoding().isEmpty()) {
        g.addVariable("Encoding", font.getEncoding(), 0);
    }

    PF_BlockList* letterList = font.getLetterList();
    for (uint i=0; i<font.countLetters(); ++i) {
        PF_Block* ch = font.letterAt(i);

        QString uCode;
        uCode.setNum(ch->getName().at(0).unicode(), 16);
        while (uCode.length()<4) {
            uCode="0"+uCode;
        }
        //ch->setName("[" + uCode + "] " + ch->getName());
        //letterList->rename(ch, QString("[%1]").arg(ch->getName()));
        letterList->rename(ch,
                           QString("[%1] %2").arg(uCode).arg(ch->getName().at(0)));

        g.addBlock(ch, false);
        ch->reparent(&g);
    }

    g.addBlockNotification();

	return true;
}



/**
 * Implementation of the method used for PF_Export to communicate
 * with this filter.
 *
 * @param file Full path to the FONT file that will be written.
 */
bool PF_FilterFont::fileExport(PF_Graphic& g, const QString& file, LX_Define::FormatType /*type*/) {

    PF_DEBUG->print("Font Filter: exporting file '%s'...", file.latin1());

    // crashes under windows xp:
    //std::ofstream fout;

    PF_DEBUG->print("PF_FilterFont::fileExport: open");
    //fout.open((const char*)file.local8Bit());
    FILE* fp;

    if ((fp = fopen((const char*)file.local8Bit(), "wt")) != NULL) {

        PF_DEBUG->print("PF_FilterFont::fileExport: open: OK");

        PF_DEBUG->print("PF_FilterFont::fileExport: header");

        // header:
        fprintf(fp, "# Format: Font\n");

        fprintf(fp, "# Creator:           %s\n",
                (const char*)PF_SYSTEM->getAppName().local8Bit());
        fprintf(fp, "# Version:           %s\n",
                (const char*)PF_SYSTEM->getAppVersion().local8Bit());

        PF_DEBUG->print("001");
        QString ns = g.getVariableString("Names", "");
        if (!ns.isEmpty()) {
            PF_StringList names = PF_StringList::split(',', ns);
            PF_DEBUG->print("002");
            for (PF_StringList::Iterator it = names.begin(); it!=names.end(); ++it) {
                fprintf(fp, "# Name:              %s\n",
                        (const char*)((*it).local8Bit()));
            }
        }

        PF_DEBUG->print("003");

        QString es = g.getVariableString("Encoding", "");
        if (!es.isEmpty()) {
            fprintf(fp, "# Encoding:          %s\n",
                    (const char*)es.local8Bit());
        }

        PF_DEBUG->print("004a");

        fprintf(fp, "# LetterSpacing:     %f\n",
                g.getVariableDouble("LetterSpacing", 3.0));
        fprintf(fp, "# WordSpacing:       %f\n",
                g.getVariableDouble("WordSpacing", 6.75));
        fprintf(fp, "# LineSpacingFactor: %f\n",
                g.getVariableDouble("LineSpacingFactor", 1.0));

        QString sa = g.getVariableString("Authors", "");
        PF_DEBUG->print("authors: %s", (const char*)sa.local8Bit());
        if (!sa.isEmpty()) {
            PF_StringList authors = PF_StringList::split(',', sa);
            PF_DEBUG->print("006");
            PF_DEBUG->print("count: %d", authors.count());

            QString a;
            for (PF_StringList::Iterator it2 = authors.begin();
                    it2!=authors.end(); ++it2) {

                PF_DEBUG->print("006a");
                a = QString(*it2);
                PF_DEBUG->print("006b");
                PF_DEBUG->print("string is: %s", a.ascii());
                PF_DEBUG->print("006b0");
                fprintf(fp, "# Author:            ");
                PF_DEBUG->print("006b1");
                fprintf(fp, "%s\n", a.ascii());
                //fout << "# Author:            " << a.ascii() << "\n";
            }
            PF_DEBUG->print("007");
        }

        PF_DEBUG->print("PF_FilterFONT::fileExport: header: OK");

        PF_DEBUG->print("008");
        // iterate through blocks (=letters of font)
        for (uint i=0; i<g.countBlocks(); ++i) {
            PF_Block* blk = g.blockAt(i);

            PF_DEBUG->print("block: %d", i);
            PF_DEBUG->print("001");

            if (blk!=NULL) {
                PF_DEBUG->print("002");
                PF_DEBUG->print("002a: %s",
                                (const char*)(blk->getName().local8Bit()));

                fprintf(fp, "\n%s\n",
                        (const char*)(blk->getName().local8Bit()));


                // iterate through entities of this letter:
                for (PF_Entity* e=blk->firstEntity(LX_Define::ResolveAll);
                        e!=NULL;
                        e=blk->nextEntity(LX_Define::ResolveAll)) {

                    if (!e->isUndone()) {

                        PF_DEBUG->print("004");

                        // lines:
                        if (e->rtti()==LX_Define::EntityLine) {
                            PF_Line* l = (PF_Line*)e;

                            fprintf(fp, "L %f,%f,%f,%f\n",
                                    l->getStartpoint().x,
                                    l->getStartpoint().y,
                                    l->getEndpoint().x,
                                    l->getEndpoint().y);
                        }

                        // arcs:
                        else if (e->rtti()==LX_Define::EntityArc) {
                            PF_Arc* a = (PF_Arc*)e;

                            if (!a->isReversed()) {
                                fprintf(fp, "A ");
                            } else {
                                fprintf(fp, "AR ");
                            }

                            fprintf(fp, "%f,%f,%f,%f,%f\n",
                                    a->getCenter().x,
                                    a->getCenter().y,
                                    a->getRadius(),
                                    a->getAngle1()*ARAD,
                                    a->getAngle2()*ARAD);
                        }
                        // Ignore entities other than arcs / lines
                        else {}
                    }

                    PF_DEBUG->print("005");
                }
                PF_DEBUG->print("006");
            }
            PF_DEBUG->print("007");
        }
        //fout.close();
        fclose(fp);
    	PF_DEBUG->print("font Filter: exporting file: OK");
		return true;
    }
	else {
    	PF_DEBUG->print("font Filter: exporting file failed");
	}

	return false;
}



/**
 * Streams a double value to the gien stream cutting away trailing 0's.
 *
 * @param value A double value. e.g. 2.700000
 */
void PF_FilterFont::stream(std::ofstream& fs, double value) {
    fs << (const char*)PF_Utility::doubleToString(value);
}

